<?php
/**
 * This file is part of League of Legends PHP Inibin Parser.
 *
 * League of Legends PHP Inibin Parser is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * League of Legends PHP Inibin Parser is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with League of Legends PHP Inibin Parser.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * League of Legends Client-Database parser
 * Class: parser
 *
 * @author Marcel Klimek <klimek@secondred.de>
 * @copyright Marcel Klimek
 * @deprecated This is just the parser for the old League of Legend inibin files
 * @version $Id: class.inibin.parser_old.php 3 2011-11-12 10:07:44Z naffto88@gmail.com $
 */
class parser
{
    /**
     * Debug-Mode
     * @var boolean 
     */
    private $bDebug = false;

    /**
     * Storage for the binary data of the current file
     * @var byte(string)
     * @access private
     */
	private $binfile = null;

    /**
     * Number of Entries in the current File
     * @var integer
     * @access private
     */
	private $iNumberOfEntries = 0;

    /**
     * Size of the Data-Bytes in the current files
     * @var integer
     * @access private
     */
	private $iSizeOfData = 0;

    /**
     * Size of the Header + Key Bytes at the beginning of the current File
     * @var integer
     * @access private
     */
	private $iDataOffset = 0;

    /**
     * The whole filesize
     * @var integer
     * @access private
     */
	private $iFilesize = 0;

    /**
     * The binaray data stored in an array as Hex-Values
     * @var array
     * @access private
     */
    private $hexFile = array();

    /**
     * The binaray data stored in an array as Decimal Values
     * @var array
     * @access private
     */
    private $decFile = array();

    /**
     * Array of Key - Offset Pairs
     * @var array
     * @access private
     */
    private $arrKeyOffset = array();

    /**
     * Array of Key - Value Pairs
     * @var array
     * @access private
     */
    private $arrKeyValue = array();

    /**
     * The name of the current file
     * @var string
     */
    private $strFilename = "";

    
    /**
     * Returns the Value which corresponds to the Key
     * 
     * @param String $strKey
     * @return mixed String, Long, Int
     * @access public
     */
    public function getValue($strKey)
    {
        if (array_key_exists((string) $strKey, $this->arrKeyValue))
            return $this->arrKeyValue[(string) $strKey];
        else return 0;
    }


    private function resetClassVars()
    {
        $this->binfile = "";
        $this->arrKeyOffset = array();
        $this->arrKeyValue = array();
        $this->decFile = array();
        $this->hexFile = array();
        $this->iDataOffset = 0;
        $this->iFilesize = 0;
        $this->iNumberOfEntries = 0;
        $this->iSizeOfData = 0;
    }


    /**
     * Loads the File and parse all Values and Keys
     *
     * @param String $strFilePath
     * @return boolean False - File doesn't exist
     * @access public
     */
    public function loadFile($strFilePath)
    {
        if (!file_exists($strFilePath))
            return false;
        
        //get the filename
        $arrFilenames = explode(DIRECTORY_SEPARATOR,$strFilePath);
        $arrFilenames = explode('.',$arrFilenames[count($arrFilenames)-1]);
        $this->strFilename = $arrFilenames[0];

        //reset all class vars for the new process
        $this->resetClassVars();
        
        $datei = fopen($strFilePath,"rb");
        $this->iFilesize = filesize($strFilePath);
        $this->binfile = fread($datei,$this->iFilesize);
        
        //workaround for php
        $strHex = unpack('H*',$this->binfile);
        $this->splitToHexArray($strHex[1]);
        $this->_hex8dec($strHex[1]);
        
        $this->parseHeader();
    }


    /**
     *  This method fill the class var $decFile with the corresponding Decimal values
     *  It will convert the $strHex in 8-bit steps
     *
     * @param String $strHex The full Hex-String of the Binary File
     * @param integer $i    The current Position in the Hex-String
     * @param boolean $unsigned Convert to unsigned Value
     * @access private
     */
    private function _hex8dec($strHex,$i = 0,$unsigned = false)
    {
        $iStart = $i * 2;
        $strHexVal = substr($strHex,$iStart,2);
        $num = hexdec($strHexVal);

        if($num > 0xFF)
        {
            $this->decFile[$i] = 99999;
        }
        
        if($num >= 0x80 && $unsigned == false)
        {
            $this->decFile[$i] = -(($num ^ 0xFF)+1);
        } else
        {
            $this->decFile[$i] = $num;
        }
        
        if ($iStart+2 < strlen($strHex))
        {
            $i++;
            $this->_hex8dec($strHex,$i);
        }
    }


    /**
     * This method will return the Decimal Value for $strHex
     *
     * @param String $strHex An 16-Bit Hex-Value
     * @param boolean $unsigned Convert to unsigned Value
     * @access private
     */
    private function hex16dec($strHex,$unsigned = false)
    {
        $num = hexdec($strHex);

        if($num > 0xFFFF)
        {
            return false;
        }

        if($num >= 0x8000 && $unsigned == false)
        {
            $num = -(($num ^ 0xFFFF)+1);
        } else
        {
        }

        return $num;
    }


    /**
     * This method will return the Decimal Value for $strHex
     *
     * @param String $strHex An 32-Bit Hex-Value
     * @param boolean $unsigned Convert to unsigned Value
     * @access private
     */
    private function hex32dec($strHex,$unsigned = false)
    {
        $num = hexdec($strHex);

        if($num > 0xFFFFFFFF)
        {
            return false;
        }

        if($num >= 0x80000000 && $unsigned == false)
        {
            $num = -(($num ^ 0xFFFFFFFF)+1);
        } else
        {
        }

        return $num;
    }


    /**
     * This Method splits the raw binaray File into an full Hex-String
     *
     * @param byte(String) $binFile
     * @param integer $i
     * @access private;
     */
    private function splitToHexArray($binFile,$i = 1)
    {
        $iStart = $i * 2;
        $this->hexFile[$i] = substr($binFile,$iStart,2);

        if ($iStart+2 < strlen($binFile))
        {
            $i++;
            $this->splitToHexArray($binFile,$i);
        }
    }


    /**
     * This method fills $strHex with a preceding zero when necessary
     *
     * @param String $strHex
     * @return string
     * @access private
     */
    private function fixHexStr($strHex)
    {
		if (strlen($strHex) == 1) $strHex = "0" . $strHex;
		if (strlen($strHex) > 2) $strHex = substr($strHex,strlen($strHex)-2);
        if (strlen($strHex) == 0) $strHex = "00";

		return $strHex;
	}


    /**
     * This Method will return the correct decimal Value of the given 4 Bytes
     * with the Little Endian method
     *
     * @param int $bA
     * @param int $bB
     * @param int $bC
     * @param int $bD
     * @return int/long
     * @access private
     */
    private function hexLittleEndianToDec($bA, $bB, $bC, $bD)
    {
		$strtmp = "";
		$strtmp = $this->fixHexStr(dechex($bD)) . $this->fixHexStr(dechex($bC)) . $this->fixHexStr(dechex($bB)) . $this->fixHexStr(dechex($bA));

        return $this->hex32dec($strtmp,true);
	}


    /**
     * This Method will return the correct decimal Value of the given 2 Bytes
     * with the Little Endian method
     *
     * @param int $bA
     * @param int $bB
     * @return int/long
     * @access private
     */
    private function hexLittleEndianToDec2($bA, $bB)
    {
		$strtmp = "";
		$strtmp = $this->fixHexStr(dechex($bB)) . $this->fixHexStr(dechex($bA));

        return $this->hex16dec($strtmp);
	}


    /**
     * This Method will parse the whole File and will exclude all
     * Keys, Offsets and Values into the 2 main arrays of the class
     *
     * @access private
     */
    private function parseHeader()
    {
        $this->iNumberOfEntries = $this->hexLittleEndianToDec2((0xff & $this->decFile[4]),(0xff & $this->decFile[5]));
		$this->iSizeOfData = $this->hexLittleEndianToDec2((0xff & $this->decFile[8]),(0xff & $this->decFile[9]));

		$this->iDataOffset = (int) ($this->iFilesize - $this->iSizeOfData);
		$strKey = "";
		$strOffset = "";
		for($i = 0;$i < $this->iNumberOfEntries; $i++)
        {
			$strKey = $this->hexLittleEndianToDec($this->decFile[(12 + $i *8)], $this->decFile[(13 + $i *8)],$this->decFile[(14 + $i *8)], $this->decFile[(15 + $i *8)]);
			$strOffset = $this->hexLittleEndianToDec2($this->decFile[(16 + $i *8)], $this->decFile[(17 + $i *8)]);

            //hack for php's integer values....
            $this->arrKeyOffset["".$strKey.""] = $strOffset;
            $this->arrKeyValue["".$strKey.""] = $this->getData($strOffset);
			$this->debug("Offset: " . $strOffset . " Key: " . $strKey . " Value: " . $this->getData($strOffset));
		}
    }


    /**
     * This Method gets the Value from the File at the specific offset
     * This method searches for the next \0x00 Byte to determine the end of an
     * value
     *
     * @param integer,long $strOffset
     * @return mixed Value for the Offset
     * @access private
     */
    private function getData($strOffset)
    {
        $i = $this->iDataOffset + $strOffset;
		$strReturn = "";

		while($i < $this->iFilesize)
        {
			if (count($this->decFile) > $i)
				$iASCII = $this->decFile[$i];
			else
				continue;

			if($iASCII == 0)
            {
				return $strReturn;
			} else
            {
				$strReturn .= (string) chr($iASCII);
			}
			$i++;
		}

        return $strReturn;
    }


    /**
     * This is the debug Method for this class
     *
     * @param string $strDebug
     * @access private
     */
    private function debug($strDebug)
    {
        if ($this->bDebug == true)
            echo "[DEBUG] " . $strDebug . "<br/>";
    }


    /**
     * Sets the Debug-Mode
     *
     * @param boolean $bDebug
     * @access public
     */
    public function setDebug($bDebug)
    {
        $this->bDebug = $bDebug;
    }


    /**
     * Returns the name of the current file
     * 
     * @return string
     * @access public
     */
    public function getFilename()
    {
        return $this->strFilename;
    }
}
?>